﻿
/// <reference path="../BaseObject.js" />
/// <reference path="_namespace.js" />
/// <reference path="Colour.js" />
/// <reference path="../math/Matrix.js" />
/// <reference path="../math/Vector3.js" />
/// <reference path="Face.js" />
/// <reference path="Viewport.js" />
/// <reference path="LightTypes.js" />
/// <reference path="Light.js" />


/*****************************************************************************
Ajax library class definition. Kevin Robinson 2006.
Class: ajax.drawing.RenderFace
/*****************************************************************************/

ajax.lang.addNamespace("ajax.drawing");
$imports("ajax.drawing.Colour");
$imports("ajax.math.Vector3");
$imports("ajax.drawing.LightTypes");

//-----------------------------------------------------------------------------
ajax.drawing.RenderFace = function(face, cameraNormal, cameraVB, screenVerts, zBias)
{    
    if (face)
    {    
	    this.color		        = face.getColor();
	    this.cameraSpaceVertA   = cameraVB[face.v1];
	    this.cameraSpaceVertB   = cameraVB[face.v2];
	    this.cameraSpaceVertC   = cameraVB[face.v3];
	    this.screenSpaceVerts   = new Array(3);	
	    this.screenSpaceVerts[0]= screenVerts[face.v1];
	    this.screenSpaceVerts[1]= screenVerts[face.v2];
	    this.screenSpaceVerts[2]= screenVerts[face.v3];
	    this.normal             = cameraNormal;	    
	}
	this.averageZ           = 0;
	this.zBias              = zBias;
	this.lights             = [];
}		

//-----------------------------------------------------------------------------
ajax.lang.extend("ajax.drawing.RenderFace", "ajax.BaseObject"); // Inherit
//-----------------------------------------------------------------------------

// For ms ajax
ajax.drawing.RenderFace.prototype.lights = [];
ajax.drawing.RenderFace.prototype.color = ajax.drawing.Colour.prototype;
ajax.drawing.RenderFace.prototype.cameraSpaceVertA = ajax.math.Vector3.prototype;
ajax.drawing.RenderFace.prototype.cameraSpaceVertB = ajax.math.Vector3.prototype;
ajax.drawing.RenderFace.prototype.cameraSpaceVertC = ajax.math.Vector3.prototype;
ajax.drawing.RenderFace.prototype.screenSpaceVerts = [];
ajax.drawing.RenderFace.prototype.normal = ajax.math.Vector3.prototype;
ajax.drawing.RenderFace.prototype.averageZ = 0;
ajax.drawing.RenderFace.prototype.zBias = 0;
ajax.drawing.RenderFace.prototype.cullMode = 0;
ajax.drawing.RenderFace.prototype.fillMode = 0;
ajax.drawing.RenderFace.prototype.lighting = false;


//Static
ajax.drawing.RenderFace.computeColor = function(renderFace, device)
{///<param name="renderFace" type="ajax.drawing.RenderFace"/>
 ///<param name="device" type="ajax.drawing.Device3D"/>
        
    // If lighting is off then there is nothing to do
    //if (!device.renderState.lighting) // Each face now holds the data of if it is affected by lighting or not.    
    if (!renderFace.lighting)            
        return renderFace.color;
    
    
    // If lighting is ON but no lights are enabled, return black
    if (renderFace.lights.length < 1 || renderFace.lights[0].enabled == false)
        return new ajax.drawing.Colour(0, 0, 0);
    /*
    if (device.lights.length < 1 || device.lights[0].enabled == false)
        return new ajax.drawing.Colour(0, 0, 0);
    */
    // Will hold the final light intensity for each light (Cannot be > 1)
    // We calc this by adding how much light intensity each ADDS to the face    
    var rIntensity = 0; var gIntensity = 0; var bIntensity = 0;
    
    //for (var i = 0; i < device.lights.length; i++)
    for (var i = 0; i < renderFace.lights.length; i++)
    {
        var light = ajax.drawing.Light.cast(renderFace.lights[i]);        
        //var light = ajax.drawing.Light.cast(device.lights[i]);
        
        // Break when we get to a light that is not enabled.
        if (!light.enabled)
            break;
        
        var lightDirectionTransformedNormalised = new ajax.math.Vector3(0, 0, 0);
        
        switch (light.type)
        {
            case ajax.drawing.LightTypes.Directional:          
                lightDirectionTransformedNormalised = ajax.math.Matrix.transformNormal(device.transform.view, light.direction);
                break;
            case ajax.drawing.LightTypes.Omni:
                
                var lightPositionTransformed = ajax.math.Matrix.transformVertex(device.transform.view, light.position);
            
                lightDirectionTransformedNormalised = ajax.math.Vector3.normalize(ajax.math.Vector3.subtract(renderFace.cameraSpaceVertA, lightPositionTransformed));
                
                break;
            default:
                break;
            
        }
        
        // Get the Cosign of the angle between the light direction and the face normal
        var cosAngle = ajax.math.Vector3.dot(renderFace.normal, lightDirectionTransformedNormalised);
        if (cosAngle > 0)
        {
            // Facing away so apply only ambient lighting            
            rIntensity += light.getRAmbientIntensity();
            gIntensity += light.getGAmbientIntensity();
            bIntensity += light.getBAmbientIntensity();
            
        }
        else
        {            
            rIntensity += (-cosAngle * light.getRDiffuseIntensity()) + light.getRAmbientIntensity();
            gIntensity += (-cosAngle * light.getGDiffuseIntensity()) + light.getGAmbientIntensity();
            bIntensity += (-cosAngle * light.getBDiffuseIntensity()) + light.getBAmbientIntensity(); 
            
        }                        
    }
    
    var rVal = parseInt( ( rIntensity * parseFloat(renderFace.color.r) ) );
    var gVal = parseInt( ( gIntensity * parseFloat(renderFace.color.g) ) );
    var bVal = parseInt( ( bIntensity * parseFloat(renderFace.color.b) ) );
    
    rVal = Math.max(Math.min(rVal, 255), 0);
    gVal = Math.max(Math.min(gVal, 255), 0);
    bVal = Math.max(Math.min(bVal, 255), 0);
    
    return new ajax.drawing.Colour(rVal, gVal, bVal);    
}

//-----------------------------------------------------------------------------
ajax.drawing.RenderFace.prototype.computeColor = function(device)
{///<returns type="ajax.drawing.Colour"/>
    // TODO: Compute Color
    return ajax.drawing.RenderFace.computeColor(this, device);
}

//-----------------------------------------------------------------------------
ajax.drawing.RenderFace.prototype.reComputeCameraToScreen = function(viewport)
{///<param name="viewport" type="ajax.drawing.Viewport"/>       
	var cameraVerts = new Array(3);
	cameraVerts[0] = this.cameraSpaceVertA;
	cameraVerts[1] = this.cameraSpaceVertB;
	cameraVerts[2] = this.cameraSpaceVertC;
	    
	this.screenSpaceVerts = viewport.computeCameraToScreen(cameraVerts);
}

//-----------------------------------------------------------------------------
ajax.drawing.RenderFace.prototype.computeAverageZ = function()
{
	this.averageZ = 0.33333 * (
		this.cameraSpaceVertA.z +
		this.cameraSpaceVertB.z+ 
		this.cameraSpaceVertC.z) + this.zBias;
}

//-----------------------------------------------------------------------------
ajax.drawing.RenderFace.prototype.setAverageZ = function(value)
{///<summary>Used only by internal rendering methods. Clients should use calculateAverageZ() method.</summary>
    this.averageZ = value;
}

//-----------------------------------------------------------------------------
ajax.drawing.RenderFace.prototype.toString = function()
{
    return "ajax.drawing.RenderFace";
}

//-----------------------------------------------------------------------------
ajax.drawing.RenderFace.create = function(camSpaceVertA, camSpaceVertB, camSpaceVertC, colour, camSpaceNormal, viewport)
{///<summary>Factory creator - an Alternative "constructor"</summary>
 ///<returns type="ajax.drawing.RenderFace"/>
 ///<param name="camSpaceVertA" type="ajax.math.Vector3"/>
 ///<param name="camSpaceVertB" type="ajax.math.Vector3"/>
 ///<param name="camSpaceVertC" type="ajax.math.Vector3"/>
 ///<param name="colour" type="ajax.drawing.Colour"/>
 ///<param name="camSpaceNormal" type="ajax.math.Vector3"/>
 ///<param name="viewport" type="ajax.drawing.Viewport"/>
 
    var ret = new ajax.drawing.RenderFace(); // no args
    ret.color = colour;
    ret.cameraSpaceVertA = camSpaceVertA;
    ret.cameraSpaceVertB = camSpaceVertB;
    ret.cameraSpaceVertC = camSpaceVertC;
    
    ret.reComputeCameraToScreen(viewport);
    ret.normal = camSpaceNormal;
    
    return ret;
 
}

//-----------------------------------------------------------------------------
ajax.drawing.RenderFace.cast = function(obj)
{///<returns type="ajax.drawing.RenderFace"/>
    return obj;    
}



